import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import { MAINHOST, ISMOCK, conmomPrams } from '@/config'
import { getToken } from '@/utils/common'
import URL from '@/config/publicUrl.ts'
import { Loading, Message } from 'element-ui'
import router from '@/router'

declare type Methods =
  | 'GET'
  | 'POST'
  | 'OPTIONS'
  | 'HEAD'
  | 'PUT'
  | 'DELETE'
  | 'TRACE'
  | 'CONNECT'
declare interface Datas {
  [key: string]: any
}
const token = getToken()

const baseUrl =
  process.env.NODE_ENV === 'production' ? MAINHOST : location.origin

class HttpRequst {
  private query: any
  private load: any
  public constructor() {
    this.query = {}
  }
  public async request(option: AxiosRequestConfig) {
    const Axios = axios.create()
    await this.interceptors(Axios, option.url)
    return Axios(option)
  }
  private destroy(url: string) {
    delete this.query[url]
    if (!Object.keys(this.query).length) {
      // 去除loading
      this.load.close()
    }
  }
  // 拦截
  private interceptors(Ajax: any, url?: string) {
    // 请求拦截
    Ajax.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        if (url) {
          this.query[url] = true
        }
        if (Object.keys(this.query).length) {
          // 添加loading
          this.load = Loading.service({})
        }
        return config
      },
      (err: any) => {
        Message.error(err.message)
      }
    )

    // 相应拦截
    Ajax.interceptors.response.use(
      (response: AxiosResponse) => {
        if (url) {
          this.destroy(url)
        }
        const { data, status } = response
        // mock
        if (status === 200 && ISMOCK) {
          return data
        }
        // server
        if (status === 200 && data && data.code === 0) {
          return data
        }
        // 失败处理
        return requestFail(response)
      },
      (err: any) => {
        if (url) {
          this.destroy(url)
        }
        Message.error(err.message)
      }
    )
  }
}
const requestFail = (response: AxiosResponse) => {
  // 失败请求处理
  const { data, status } = response
  const errStr = '网络繁忙！'
  if (data.code === 1000001) {
    Message.warning('登录已过期，请重新登录')
    return router.replace({ name: 'Home' })
  }
  Message.error(data.errorMessage || errStr)
  return response
}
// 合并axios参数
const conbineOptions = (
  options: AxiosRequestConfig | string,
  data: Datas,
  method: Methods
): AxiosRequestConfig => {
  let opt!: AxiosRequestConfig
  if (typeof options === 'string') {
    opt = {
      url: options,
    }
  } else {
    opt = options
  }
  const DATA = { ...conmomPrams, ...opt.data, ...data }
  const opts = {
    url: opt.url,
    method: data.method || opt.method || method || 'GET',
    header: { 'user-token': token },
    baseUrl,
  }
  return opts.method === 'GET'
    ? Object.assign(opts, { params: DATA })
    : Object.assign(opts, { data: DATA })
}
const HTTP = new HttpRequst()

let Api: any = (() => {
  const ajaxObj: Datas = {}
  const fun = (options: AxiosRequestConfig | string) => {
    return async (data = {}, method: Methods = 'GET') => {
      if (!token) {
        Message.error('No Token')
        return router.replace({ name: 'Home' })
      }
      // 所有数据合并
      let datas = conbineOptions(options, data, method)
      let res = await HTTP.request(datas)
      return res
    }
  }
  Object.keys(URL).forEach((key) => {
    ajaxObj[key] = fun(URL[key])
  })
  return ajaxObj
})()

export default Api as any
